package com.ruoyi.project.download;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;

/**
 * @author bc
 */
@Slf4j
public class DownloadReadFileUtils {

  /**
   * read file content
   */
  public static long readFileContent(HttpServletRequest request, HttpServletResponse response,
                                     File file) throws IOException {
    boolean first = true;
    long length = file.length();
    if (length <= 0L) {
      return 0;
    }
    long start = 0;
    long end = length - 1;
    long[] range = parseRangeBytes(request);
    if (range != null) {
      start = range[0] > 0L ? range[0] : start;
      end = range[1] > 0L ? range[1] : end;
      response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
      response
          .addHeader("Content-Range", "bytes " + start + "-" + Math.max(start, end) + "/" + length);
    } else {
      response.setStatus(HttpServletResponse.SC_OK);
    }
    response.setHeader("Content-disposition", "attachment; filename=" + file.getName());
    response.addHeader("Accept-Ranges", "bytes");
    response.addHeader("Content-Length", Long.toString(end - start + 1));
    long pos = start;
    if (start < end) {
      InputStream input = null;
      ServletOutputStream output = null;
      try {
        input = new FileInputStream(file);
        if (pos != 0L) {
          input.skip(pos);
        }
        output = response.getOutputStream();
        byte[] buffer = new byte[8 * 4096];
        int bytesRead = 0;
        while ((pos < end) && ((bytesRead = input.read(buffer)) != -1)) {
          output.write(buffer, 0, bytesRead);
          pos += bytesRead;
          if (first) {
            first = false;
          }
        }
        output.flush();
      } catch (SocketException e) {
      } catch (Exception e) {
        log.error("open file exception: " + pos + ", " + end);
      } finally {
        if (input != null) {
          input.close();
        }
        if (output != null) {
          output.close();
        }
      }
    }
    return 0;
  }

  private static long[] parseRangeBytes(HttpServletRequest request) {
    String range = request.getHeader("Range");
    if (range != null) {
      int index = range.indexOf("bytes");
      if (index >= 0) {
        long[] rangePos = new long[2];
        range = range.substring(6);
        index = range.indexOf("-");
        rangePos[0] = index == 0 ? 0 : Long.parseLong(range.substring(0, index));
        range = range.substring(index + 1);
        if (range.length() == 0) {
          rangePos[1] = -1;
        } else {
          index = range.indexOf(",");
          rangePos[1] =
              index < 0 ? Long.parseLong(range) : Long.parseLong(range.substring(0, index));
        }
        return rangePos;
      }
    }
    return null;
  }
}
